/**
 * Class Mobile
 * this class is used to manage based function
 * like screen size, orientation, some windows events and others
 */
Mobile = (function() {

    /**
     * Mobile constructor
     * @param application {Application} application instance
     * @constructor
     */
    function Mobile(application) {
        var _this = this;
        this.application = application;
        this.window = new View(window);
        this.body = new View(document.body);
        this.head = new View(document.head);
        this.contents = new Views(".content");
        this.wrapper = new View("wrapper");
        this.checker = new Checker;
        this.cacheupdated = false;
        this.window.addEvent('load', function() {
            return _this.documentLoaded();
        });
        this.window.addEvent("orientationchange", function() {
            return _this.documentRotate();
        });
        this.window.addEvent("resize", function() {
            if (_this.checker.types.iphone) {
                _this.fixiPhoneLandscape();
            }
            return _this.documentRotate();
        });
        if ("applicationCache" in window) {
            window.applicationCache.addEventListener('updateready', function(e) {
                _this.cacheupdated = true;
                if(_this.cacheUpdatedListener)
                    _this.cacheUpdatedListener.call(_this,e);
            });
            window.applicationCache.addEventListener('noupdate', function(e) {
                if(_this.cacheLoadedListener)
                    _this.cacheLoadedListener.call(_this, e);
            });
            window.applicationCache.addEventListener('cached', function(e) {
                if(_this.cachedListener)
                    _this.cachedListener.call(_this, e);
            });
        }
        this.size = {};
    }
    /**
     * Set on chache updated listener
     * @param listener {Function} chache updated listener
     */
    Mobile.prototype.setOnCacheUpdatedListener = function(listener) {
        this.cacheUpdatedListener = listener;
    };
    /**
     * Set on chache loaded listener
     * @param listener {Function} chache loaded listener
     */
    Mobile.prototype.setOnCacheLoadedListener = function(listener) {
        this.cacheLoadedListener = listener;
    };
    /**
     * Set on chached listener
     * @param listener {Function} chached listener
     */
    Mobile.prototype.setOnCachedListener = function(listener) {
        this.cachedListener = listener;
    };
    /**
     * Create Metatag based on platform
     */
    Mobile.prototype.createMethaTag = function() {
        var content;
        this.meta = new View(document.getElementsByName('viewport')[0] || document.createElement('meta'));
        this.meta.attr({
            name: "viewport"
        });
        content = !this.checker.types.iphone5 ? "width=device-width, " : "";
        content += "target-densityDpi=160, ";
        content += "initial-scale=1.0, minimum-scale=1.0, maximum-scale=1, user-scalable=no";
        this.meta.attr({
            content: content
        });
        if (!this.meta.inDOM()) {
            this.head.append(this.meta);
        }
    };
    /**
     * Set size and remove bar
     * @param layout {String} layout orientation
     * @param time {Number} set timeout time
     */
    Mobile.prototype.removeBar = function(layout, time) {
        this.layout = layout;
        if (this.checker.types.iphone && !this.checker.types.fullscreen) {
            if (this.layout && this.layout === "landscape") {
                this.wrapper.style({
                    height: "" + (window.innerHeight < this.size.width ? this.size.width - 52 : this.size.width) + "px"
                });
                this.wrapper.style({
                    width: "" + this.size.height + "px"
                });
            } else {
                this.wrapper.style({
                    height: "" + (this.size.height - 64) + "px"
                });
                this.wrapper.style({
                    width: "" + this.size.width + "px"
                });
            }
        }
        if (this.checker.types.android && !this.checker.types.chrome) {
            if (this.layout && this.layout === "landscape") {
                this.wrapper.style({
                    height: "" + (this.size.width - (12 * this.size.dpi)) + "px"
                });
                this.wrapper.style({
                    width: "" + this.size.height + "px"
                });
            } else {
                this.wrapper.style({
                    height: "" + (this.size.height - (12 * this.size.dpi)) + "px"
                });
                this.wrapper.style({
                    width: "" + this.size.width + "px"
                });
            }
        }
        this.hideBar(time);
    };
    /**
     * Hide bar by scrolling on top after some time
     * @param time {Number} hide after this time
     */
    Mobile.prototype.hideBar = function(time) {
        setTimeout(function() {
            window.scrollTo(0, 0);
        }, time || 50);
    };
    /**
     * Fix iPhone landscape fullscreen
     */
    Mobile.prototype.fixiPhoneLandscape = function() {
        this.removeBar(this.layout);
    };
    /**
     * Detect orientation
     * @returns {boolean} if orientation was change or not
     */
    Mobile.prototype.detectOrientation = function() {
        var _layout = this.layout;
        if ("orientation" in window) {
            this.layout = Math.abs(window.orientation) ? "landscape" : "portrait";
        } else {
            this.layout = window.outerWidth > window.outerHeight ? "landscape" : "portrait";
        }
        if(_layout === this.layout) return false;
        this.body.removeClass("lanscape portrait");
        this.body.addClass(this.layout);
        return true;
    };
    /**
     * Set on load listener
     * @param listener {Functon} load listener
     */
    Mobile.prototype.setOnLoadListener = function(listener) {
        this.loadListener = listener;
    };
    /**
     * On document loaded
     */
    Mobile.prototype.documentLoaded = function() {
        this.createMethaTag();
        if (this.checker.types.iphone) {
            this.size.width = Math.min(window.screen.width, window.screen.height);
            this.size.height = Math.max(window.screen.width, window.screen.height);
            this.body.addClass('iphone');
        } else {
            this.size.width = Math.round((Math.min(window.screen.width, window.screen.height)) / window.devicePixelRatio);
            this.size.height = Math.round((Math.max(window.screen.width, window.screen.height)) / window.devicePixelRatio);
            this.size.dpi = window.devicePixelRatio;
            this.body.addClass('android');
        }
        this.detectOrientation();
        if (this.checker.types.iphone && this.layout === "landscape") {
            this.fixiPhoneLandscape();
        }

        this.removeBar(this.layout);
        if(this.loadListener) this.loadListener.call(this);
    };
    /**
     * On document rotate
     */
    Mobile.prototype.documentRotate = function() {
        if(this.detectOrientation()) this.removeBar(this.layout, this.checker.types.android ? 1000 : 50);
    };
    /**
     * Class Checker
     * is user to check device and device version
     */
    Checker = (function() {
        /**
         * Checker constructor
         * @constructor
         */
        function Checker() {
            this.ua = navigator.userAgent;
            this.types = {};
            this.types.iphone = this.ua.match(/(iPhone|iPod)/);
            this.types.iphone5 = this.types.iphone && window.screen.height === 568;
            this.types.ipad = this.ua.match(/iPad/);
            this.types.chrome = this.ua.match(/Chrome/);
            this.types.android = this.ua.match(/Android ([0-9](.[0-9])?)/);
            this.types.ie = this.ua.match(/MSIE/);
            this.types.fullscreen = navigator.standalone;
        }

        /**
         * Get all device types
         * @returns {*}
         */
        Checker.prototype.get = function() {
            return this.types;
        };

        return Checker;

    })();

    return Mobile;

})();